package main

import (
	"encoding/json"
	"fmt"
	"io"
	"nat_detect"
	"net"
)

func handleConn(conn net.Conn) {
	for {
		buf := make([]byte, 1000)
		n, err := conn.Read(buf)
		if err == io.EOF {
			break
		}
		data := buf[:n]
		p := nat_detect.RawPkt{}

		json.Unmarshal(data, &p)
		fmt.Println(p.Cmd)

		udpAddr, _ := net.ResolveUDPAddr("udp4", p.Remote)
		udpConn, err := net.DialUDP("udp", nil, udpAddr)
		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Println("test2 : udp dial ", p.Remote, "ok ")
		n, err2 := udpConn.Write(data)
		if err2 != nil {
			fmt.Println(err)
			return
		}

		break
		//简化逻辑，每个conn只处理一个命令

	}
}
func handleTest1(pkt nat_detect.RawPkt, conn *net.UDPConn, remoteAddr *net.UDPAddr) {
	echoPkt := nat_detect.RawPkt{
		Cmd:    "test1-echo",
		Id:     pkt.Id,
		Remote: remoteAddr.String(),
	}
	echo, _ := json.Marshal(echoPkt)
	fmt.Println("echo to ", echoPkt.String())
	_, err := conn.WriteToUDP(echo, remoteAddr)
	if err != nil {
		fmt.Println(err)
		return
	}
}

func handlePkt(pkt nat_detect.RawPkt, remoteAddr *net.UDPAddr, conn *net.UDPConn) {
	switch pkt.Cmd {
	case "test1":
		fmt.Println("cmd test1")
		handleTest1(pkt, conn, remoteAddr)
	}
}

func ListenUdp() {
	const port = 9999
	conn, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   net.ParseIP("0.0.0.0"),
		Port: port,
	})
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	fmt.Printf("listent udp port %d \n", port)
	buf := make([]byte, 512) //一般认为udp包不要超过512 bytes
	for {
		rlen, remoteAddr, err := conn.ReadFromUDP(buf)
		if err != nil {
			fmt.Println("conn.ReadFromUDP error", err)
			continue
		}
		p := nat_detect.RawPkt{}
		json.Unmarshal(buf[:rlen], &p)
		go handlePkt(p, remoteAddr, conn)

	}
}

func main() {
	go ListenUdp()

	const port = 9900
	lis, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port))
	if err != nil {
		panic(err)
	}
	fmt.Println("listen tcp ", port)
	for {
		conn, err := lis.Accept()
		if err != nil {
			panic(err)
		}
		go handleConn(conn)
	}
}
